package com.zl.bcyappserver.service.retrofit;

import com.google.gson.JsonSyntaxException;
import com.zl.bcyappserver.domain.dao.Picture;
import com.zl.bcyappserver.domain.dao.Tag;
import com.zl.bcyappserver.domain.jsonbean.tag_analy.Image_list;
import com.zl.bcyappserver.domain.jsonbean.tag_analy.Items;
import com.zl.bcyappserver.domain.jsonbean.tag_analy.Post_tags;
import com.zl.bcyappserver.domain.jsonbean.tag_analy.TagsAnalyResult;
import com.zl.bcyappserver.domain.jsonbean.tag_catch.Infos;
import com.zl.bcyappserver.domain.jsonbean.tag_catch.TagsCatchResult;
import com.zl.bcyappserver.domain.jsonbean.works.UserWorksResult;
import com.zl.bcyappserver.dto.PictureDTO;
import com.zl.bcyappserver.dto.PicturePathDTO;
import com.zl.bcyappserver.interfaces.BcyCallback;
import com.zl.bcyappserver.utils.UserUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Observer;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by ZhongLeiDev at 2019/12/2
 */
@Slf4j
public class RetrofitBcyRequestHandle {

    private static final String BASE_API_URL = "https://bcy.net/apiv3/";
    private static final  String BASE_NET_URL = "https://bcy.net/";
    private static RetrofitBcyRequestHandle retrofitBcyRequestHandle;
    private BcyRequestService bcyApiService;
    private BcyRequestService bcyNetService;
    private static final long TIMOUT = 2000;

    private RetrofitBcyRequestHandle() {
        initRetrofitAPI();
        initRetrofitNet();
    }

    public static RetrofitBcyRequestHandle getNewInstance() {
        return new RetrofitBcyRequestHandle();
    }

    public static RetrofitBcyRequestHandle getSingletonInstance() {
        if (retrofitBcyRequestHandle == null) {
            retrofitBcyRequestHandle = new RetrofitBcyRequestHandle();
        }
        return retrofitBcyRequestHandle;
    }

    private void initRetrofitAPI() {
        Retrofit retrofit = new Retrofit.Builder()
                // 设置OKHttpClient,如果不设置会提供一个默认的
                .client(getClient())
                //设置baseUrl
                .baseUrl(BASE_API_URL)
                //添加Gson转换器
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        bcyApiService = retrofit.create(BcyRequestService.class);
    }

    private void initRetrofitNet() {
        Retrofit retrofit = new Retrofit.Builder()
                // 设置OKHttpClient,如果不设置会提供一个默认的
                .client(new OkHttpClient())
                //设置baseUrl
                .baseUrl(BASE_NET_URL)
                //添加Gson转换器
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        bcyNetService = retrofit.create(BcyRequestService.class);
    }

    /**
     * 初始化 OkHttpClient
     *添加Cookie拦截器
     * @return
     */
    private static OkHttpClient getClient() {
        OkHttpClient.Builder client = new OkHttpClient().newBuilder();

        client.interceptors().add(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                // 获取 Cookie
                okhttp3.Response resp = chain.proceed(chain.request());
                List<String> cookies = resp.headers("Set-Cookie");
                String cookieStr = "";
                if (cookies != null && cookies.size() > 0) {
                    for (int i = 0; i < cookies.size(); i++) {
                        cookieStr += cookies.get(i);
                    }
                   log.info("COOKIE-SET->" + cookieStr);
                    UserUtil.getSingletonInstance().setCookie(cookieStr.split(";")[0]);
                }
                return resp;
            }
        });
        client.interceptors().add(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                // 设置 Cookie
                String cookieStr = UserUtil.getSingletonInstance().getCookie();
                log.info("COOKIE-GET->" + cookieStr);
                if (!cookieStr.isEmpty()) {
                    return chain.proceed(chain.request().newBuilder().header("Cookie", cookieStr).build());
                }
                return chain.proceed(chain.request());
            }
        });
        client.connectTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        client.writeTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        client.readTimeout(TIMOUT, TimeUnit.MILLISECONDS);
        return client.build();
    }

    /**
     * 获取指定 Tag 的 PictureDTO 集合
     * @param id 需要获取的 Tag 的ID
     * @param page 指定获取第几页
     * @param callback 回调接口，获取数据之后的处理
     */
    public void getBcyTagDetail(String id, int page, BcyCallback<PictureDTO> callback) {
        bcyApiService.getBcyTagDetail(id, "rec:"+ String.valueOf(page), "1", "10")
                .flatMap((Func1<TagsAnalyResult, Observable<Items>>)
                        tagsAnalyResult -> Observable.from(tagsAnalyResult.getData().getItems()))
                .map(items -> {
                    PictureDTO pictureDTO = new PictureDTO();
                    List<PicturePathDTO> plist = new ArrayList<>();
                    pictureDTO.setUser_name(items.getItem_detail().getUname());
                    pictureDTO.setUid(String.valueOf(items.getItem_detail().getUid()));
                    pictureDTO.setAlbum_name(items.getItem_detail().getWork());
                    pictureDTO.setAlbum_id(String.valueOf(items.getItem_detail().getWid()));
                    pictureDTO.setCover(items.getItem_detail().getCover());
                    pictureDTO.setStars(items.getItem_detail().getLike_count());
                    StringBuilder tags = new StringBuilder();
                    for (Post_tags tag : items.getItem_detail().getPost_tags()) {
                        tags.append(tag.getTag_name());
                        tags.append(";");
                    }
                    pictureDTO.setTags(tags.toString());
                    for (Image_list img : items.getItem_detail().getImage_list()) {
                        PicturePathDTO picturePathDTO = new PicturePathDTO();
                        picturePathDTO.setPath(img.getPath());
                        picturePathDTO.setOrigin_path(covert2OriginPath(img.getPath()));
                        plist.add(picturePathDTO);
                    }
                    return pictureDTO;
                })
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(new Observer<PictureDTO>() {
                    @Override
                    public void onCompleted() {
                        callback.onSuccess("Completed!");
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        callback.onFailure("Error!");
                    }

                    @Override
                    public void onNext(PictureDTO picture) {
                        callback.onNet(picture);
                    }
                });
    }

    private String covert2OriginPath(String path) {
        //TODO 从 Path 转换到 OriginPath 的逻辑
        return path;
    }

    /**同步访问，此方法仅供测试使用*/
    public void getBcyTagDetailsCommon(String id, int page, BcyCallback<Picture> callback) throws IOException {
        Call<TagsAnalyResult> call = bcyApiService.getBcyTagDetailCommon(id,"rec:"+ String.valueOf(page), "1", "10");
        int items_count = 0;
//        log.info("ITEMSCOUNT 初始化：" + String.valueOf(items_count) + "; rec:" + String.valueOf(page));
        if (call != null) {
            Response<TagsAnalyResult> response = call.execute();
//            log.info("NEWITEM-->Since=" + response.body().getData().getItems().get(0).getSince());
            for (Items items : response.body().getData().getItems()) {
                for (Image_list img : items.getItem_detail().getImage_list()) {
                    Picture picture = new Picture();
                    picture.setUserName(items.getItem_detail().getUname());
                    picture.setUid(String.valueOf(items.getItem_detail().getUid()));
                    picture.setAlbumName(items.getItem_detail().getWork());
                    picture.setAlbumId(String.valueOf(items.getItem_detail().getWid()));
                    picture.setCover(items.getItem_detail().getCover());
                    picture.setStars(items.getItem_detail().getLike_count());
                    StringBuilder tags = new StringBuilder();
                    for (Post_tags tag : items.getItem_detail().getPost_tags()) {
                        tags.append(tag.getTag_name());
                        tags.append(";");
                    }
                    picture.setTags(tags.toString());
                    picture.setPath(img.getPath());
                    picture.setOriginPath(covert2OriginPath(img.getPath()));
                    callback.onNet(picture);
                    items_count ++;
                }
            }
            callback.onSuccess("Completed! ItemsCount=" + String.valueOf(items_count));
        } else {
            callback.onFailure("CallbackBULL->[since=rec:" + String.valueOf(page) + "; circle_id=" + id + "]");
        }
    }

    public void getBcyTagSetCommon(int offsetIndex, BcyCallback<Tag> callback) throws IOException {
        Call<TagsCatchResult> call = bcyApiService.getBcyTagsCommon(String.valueOf(20 * offsetIndex));
        Response<TagsCatchResult> response =  call.execute();
        for (Infos infos : response.body().getData().getInfos()) {
            Tag tag = new Tag();
            tag.setTagId(infos.getInfo().getCircle_id());
            tag.setTagName(infos.getInfo().getCircle_name());
            tag.setTagCover(infos.getInfo().getCover().getUrl());
            callback.onNet(tag);
        }
        callback.onSuccess("Completed!");
    }

    /**
     * 模拟登陆方法，获取cookie中的user_id字段并存储
     * @param id
     */
    public void login(String id) {
        Call<TagsAnalyResult> call = bcyApiService.getBcyTagDetailCommon(id,"rec:1", "1", "10");
        try {
            call.execute();
            log.info("---------LoginSuccess--------!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取用户所有的作品
     * @param uid
     * @param since
     * @param callback
     * @throws IOException
     */
    public void getWorksByUidCommon(String uid, String since, BcyCallback<Picture> callback) {
        Call<UserWorksResult> call = bcyApiService.getUserWorksCommon(uid, since);
        int items_count = 0;
        if (call != null) {
            Response<UserWorksResult> response = null;
            try {
                response = call.execute();
            } catch (IOException e) {
                log.error("Exception->uid=" + uid + "; since=" + since);
                e.printStackTrace();
            } catch (JsonSyntaxException exception) {
                log.error("JsonException->uid=" + uid + "; since=" + since);
                exception.printStackTrace();
            }
            for (com.zl.bcyappserver.domain.jsonbean.works.Items items : response.body().getData().getItems()) {
                since = items.getSince();
                for (com.zl.bcyappserver.domain.jsonbean.works.Image_list img : items.getItem_detail().getImage_list()) {
                    Picture picture = new Picture();
                    picture.setUserName(items.getItem_detail().getUname());
                    picture.setUid(String.valueOf(items.getItem_detail().getUid()));
                    picture.setAlbumName(items.getItem_detail().getWork());
                    picture.setAlbumId(String.valueOf(items.getItem_detail().getWid()));
                    picture.setCover(items.getItem_detail().getCover());
                    picture.setStars(items.getItem_detail().getLike_count());
                    StringBuilder tags = new StringBuilder();
                    for (com.zl.bcyappserver.domain.jsonbean.works.Post_tags tag : items.getItem_detail().getPost_tags()) {
                        tags.append(tag.getTag_name());
                        tags.append(";");
                    }
                    picture.setTags(tags.toString());
                    picture.setPath(img.getPath());
                    picture.setOriginPath(covert2OriginPath(img.getPath()));
                    callback.onNet(picture);
                    items_count ++;
                }
            }
            if (items_count > 0) {
                callback.onSuccess("COUNT="+ items_count + "#" + since);
            } else {
                callback.onFailure("All works have been Got!");
            }
        }
    }

}
